home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 426-450 / disk_441 / dme / src / cmd2.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  24KB  |  1,225 lines

  1.  
  2. /*
  3.  * CMD2.C
  4.  *
  5.  *    (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  */
  7.  
  8. #include "defs.h"
  9. #include <workbench/startup.h>
  10. #include <workbench/workbench.h>
  11.  
  12. Prototype struct _ED *uninit_init (struct _ED *);
  13. Prototype void do_remeol (void);
  14. Prototype void do_wleft (void);
  15. Prototype void do_wright (void);
  16. Prototype void do_split (void);
  17. Prototype int do_join (void);
  18. Prototype void do_margin (void);
  19. Prototype void do_wordwrap (void);
  20. Prototype void do_setparcol (void);
  21. Prototype void do_reformat (int);
  22. Prototype void do_tabstop (void);
  23. Prototype void do_insertmode (void);
  24. Prototype void do_insline (void);
  25. Prototype void do_deline (void);
  26. Prototype void do_chfilename (void);
  27. Prototype void do_edit (void);
  28. Prototype void do_bsave (void);
  29. Prototype void do_save (void);
  30. Prototype void do_saveas (void);
  31. Prototype void do_savetabs (void);
  32. Prototype void do_block (void);
  33. Prototype int blockok (void);
  34. Prototype void do_bdelete (void);
  35. Prototype void do_bcopy (void);
  36. Prototype void do_bmove (void);
  37. Prototype void do_if (void);
  38. Prototype int do_toggle (int);
  39. Prototype void do_tlate (void);
  40. Prototype void do_bsource (void);
  41. Prototype void do_scanf (void);
  42. Prototype int extend (struct _ED *, int);
  43. Prototype int makeroom (int);
  44. Prototype void freelist (char **, int);
  45.  
  46.  
  47. typedef struct WBStartup    WBS;
  48. typedef struct DiskObject   DISKOBJ;
  49.  
  50. extern void *GetDiskObject();
  51.  
  52. #define nomemory()  {memoryfail = 1;}
  53.  
  54. #if AREXX
  55. #include "rexx.h"
  56. extern int foundcmd;       /* control for implicit ARexx macro invocation   */
  57. extern int cmderr;       /* global command error flag for do_rexx()'s use */
  58. #endif
  59.  
  60. extern char MForceTitle;
  61. extern void do_bmove();
  62.  
  63. extern WBS  *Wbs;
  64.  
  65. ED *
  66. uninit_init(ep)
  67. ED *ep;
  68. {
  69.     FONT  *font;
  70.     BPTR lock = DupLock((BPTR)ep->dirlock);
  71.     WIN *win;
  72.     int bufsiz = offsetof(struct _ED,EndConfig) - offsetof(struct _ED, BeginConfig);
  73.     char *buf = malloc(bufsiz);
  74.  
  75.     movmem(&ep->BeginConfig, buf, bufsiz);
  76.     win = ep->Win;
  77.     font = ep->Font;
  78.     ep->Font = NULL;
  79.     text_uninit();
  80.     text_init(Ep, NULL, NULL);
  81.     ep = Ep;
  82.     if (ep->Font)
  83.     CloseFont(ep->Font);
  84.     ep->Win = win;
  85.     ep->Font = font;
  86.  
  87.     movmem(buf, &ep->BeginConfig, bufsiz);
  88.  
  89.     ep->Modified = 0;
  90.     ep->Line = ep->Topline = 0;
  91.     UnLock((BPTR)ep->dirlock);
  92.     ep->dirlock = (long)lock;
  93.  
  94.     free(buf);
  95.     return(ep);
  96. }
  97.  
  98. void
  99. do_remeol()
  100. {
  101.     Current[Clen = Ep->Column] = 0;
  102.     text_sync();
  103.     text_redisplaycurrline();
  104. }
  105.  
  106. void
  107. do_wleft()
  108. {
  109.     ED *ep = Ep;
  110.     int i;
  111.  
  112.     for (;;) {
  113.     i = ep->Column;
  114.     if (i == 0)
  115.         goto prevline;
  116.     --i;
  117.     while (i && Current[i] == ' ')
  118.         --i;
  119.     if (i == 0 && Current[0] == ' ') {
  120. prevline:
  121.         if (Comlinemode || ep->Line == 0) {
  122.         i = ep->Column;
  123.         break;
  124.         }
  125.         text_sync();
  126.         --ep->Line;
  127.         text_load();
  128.         ep->Column = Clen;
  129.         continue;
  130.     }
  131.     while (i && Current[i] != ' ')
  132.         --i;
  133.     if (Current[i] == ' ')
  134.         ++i;
  135.     break;
  136.     }
  137.     ep->Column = i;
  138.     text_sync();
  139. }
  140.  
  141. void
  142. do_wright()
  143. {
  144.     ED *ep = Ep;
  145.     int i;
  146.  
  147.     for (;;) {
  148.     i = ep->Column;
  149.     if (i == Clen)
  150.         goto nextline;
  151.     while (i != Clen && Current[i] != ' ')  /* skip past current word */
  152.         ++i;
  153.     while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
  154.         ++i;
  155.     if (i == Clen) {
  156. nextline:
  157.         if (Comlinemode || ep->Line == ep->Lines - 1) {
  158.         i = ep->Column;
  159.         break;
  160.         }
  161.         text_sync();
  162.         ++ep->Line;
  163.         text_load();
  164.         ep->Column = i = 0;
  165.         if (Current[0] != ' ')
  166.         break;
  167.         continue;
  168.     }
  169.     break;
  170.     }
  171.     ep->Column = i;
  172.     text_sync();
  173. }
  174.  
  175. void
  176. do_split()              /* split line in two at cursor pos */
  177. {
  178.     ubyte buf[256];
  179.     ED *ep = Ep;
  180.     RP *rp = ep->Win->RPort;
  181.     char onLastLine;
  182.  
  183.     strcpy(buf, Current+ep->Column);
  184.     Current[Clen = ep->Column] = '\0';
  185.     text_sync();
  186.     SetAPen(rp, ep->BGPen);
  187.     if (Nsu == 0)
  188.     RectFill(rp, COL(0), ROW(ep->Line-ep->Topline), Xbase+Xpixs, ROW(ep->Line-ep->Topline+1)-1);
  189.     SetAPen(rp, ep->FGPen);
  190.     text_displayseg(ep->Line - ep->Topline, 1);
  191.  
  192.     onLastLine = (ep->Line == ep->Lines-1);
  193.  
  194.     do_downadd();
  195.     if (!onLastLine)
  196.     do_insline();
  197.     strcpy(Current, buf);
  198.     Clen = strlen(Current);
  199.     text_sync();
  200.     text_displayseg(ep->Line - ep->Topline, 1);
  201.     do_up();
  202. }
  203.  
  204. do_join()
  205. {
  206.     int i = Clen, j;
  207.     ED *ep = Ep;
  208.  
  209.     if (ep->Line + 1 < ep->Lines && strlen(ep->List[ep->Line+1])+i <= 253) {
  210.     if (i && Current[i-1] != ' ')
  211.         Current[i++] = ' ';
  212.     strcpy(Current+i, ep->List[ep->Line+1]);
  213.     for (j = i; Current[j] == ' '; ++j);
  214.     for (; i >= 0 && Current[i] == ' '; --i);
  215.     if (j > i+2)
  216.         movmem(Current+j, Current+i+2, strlen(Current+j)+1);
  217.     Clen = strlen(Current);
  218.     text_sync();
  219.     text_displayseg(ep->Line - ep->Topline, 1);
  220.     {
  221.         int l = text_lineno();
  222.         do_down();
  223.         do_deline();
  224.         if (l != text_lineno())
  225.         do_up();
  226.     }
  227.     return(1);
  228.     }
  229.     return(0);
  230. }
  231.  
  232. void
  233. do_margin()
  234. {
  235.     Ep->Margin = atoi(av[1]);
  236. }
  237.  
  238. void
  239. do_wordwrap()
  240. {
  241.     ED *ep = Ep;
  242.  
  243.     if (av[1][1] == 'n')
  244.     ep->Wordwrap = 1;
  245.     if (av[1][1] == 'f')
  246.     ep->Wordwrap = 0;
  247.     if (av[1][0] == 't')
  248.     ep->Wordwrap = 1 - ep->Wordwrap;
  249.     if (ep->Wordwrap)
  250.     title("Wordwrap ON");
  251.     else
  252.     title("Wordwrap OFF");
  253. }
  254.  
  255. void
  256. do_setparcol()
  257. {
  258.     Ep->WWCol = atoi(av[1]);
  259. }
  260.  
  261. /*
  262.  * n == -1  :    force reformat entire paragraph
  263.  * n ==  0  :    only until line equalizes (from text_write())
  264.  *
  265.  * What is a paragraph?   A paragraph ends whenever the left justification
  266.  * gets larger, or on a blank line.
  267.  */
  268.  
  269. void
  270. do_reformat(n)
  271. {
  272.     char *str;
  273.     ED *ep = Ep;
  274.     RP *rp = ep->Win->RPort;
  275.     int nlok, lnsc, fnst, fnsc;
  276.     int column = ep->Column;
  277.     int srow   = ep->Line;
  278.     int crow   = srow;
  279.     int erow   = srow;
  280.     short dins = 0;        /* relative insert lines/delete lines   */
  281.     char moded = 0;        /* any modifications done at all?        */
  282.     char checked = 0;        /* for cursor positioning.            */
  283.  
  284.     if (ep->Margin == 0)
  285.     ep->Margin = 75;
  286.  
  287.     ++Nsu;
  288.     for (;;) {
  289.     str = (char *)ep->List[ep->Line+1];
  290.     fnst = 0;
  291.     fnsc = firstns(Current);
  292.     nlok = (ep->Line + 1 < ep->Lines && fnsc >= (fnst=firstns(str)));
  293.     if (ep->WWCol >= 0)
  294.         fnst = fnsc = ep->WWCol;
  295.     if (nlok && str[0] == 0)
  296.         nlok = 0;
  297.     lnsc = lastns(Current);
  298.     if (lnsc < ep->Margin) {    /* space at end of line for marg-lnsc-2 letter word   */
  299.         if (nlok == 0)        /* but no more data to joinup   */
  300.         break;          /* done */
  301.         if (ep->Margin - lnsc - 2 >= wordlen(str+fnst)) {
  302.         ep->Column = 0;
  303.         Clen = lastns(Current);
  304.         if (Current[Clen])
  305.             ++Clen;
  306.         moded = 1;
  307.         --dins;
  308.         if (do_join())
  309.             continue;
  310.         ++dins;
  311.         title("Error, Margin > 124");
  312.         break;
  313.         }
  314.         if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  315.         break;
  316.         do_down();
  317.         erow = ep->Line;
  318.         continue;
  319.     }
  320.                 /* no space, need to split    */
  321.                 /* find start of prev word    */
  322.     for (;;) {
  323.         int i = lnsc;
  324.         while (i && Current[i] != ' ')
  325.         --i;
  326.         lnsc = i;
  327.         if (i >= ep->Margin) {
  328.         while (i && Current[i] == ' ')
  329.             --i;
  330.         if (i < ep->Margin)
  331.             break;
  332.         lnsc = i;
  333.         continue;
  334.         }
  335.         break;
  336.     }
  337.     if (lnsc) {             /* ok to split at word          */
  338.         ++lnsc;
  339.         ++dins;
  340.         ep->Column = lnsc;
  341.         do_split(); /* Split at point LNSC          */
  342.         do_down();          /* must insert proper amount?   */
  343.         {
  344.         int indent = (nlok == 0) ? fnsc : fnst;
  345.         if (ep->WWCol >= 0)
  346.             indent = ep->WWCol;
  347.         if (!checked) {
  348.             checked = 1;
  349.             if (lnsc <= column) {   /* if split before cursor   */
  350.             column = column - ep->Column + indent;
  351.             ++crow;
  352.             }
  353.         }
  354.         if (Clen + indent < 253) {
  355.             movmem(Current, Current + indent, strlen(Current)+1);
  356.             setmem(Current, indent, ' ');
  357.             Clen += indent;
  358.         }
  359.         }
  360.         erow = ep->Line;
  361.         continue;
  362.     }
  363.     if (n == 0)
  364.         break;
  365.     do_down();
  366.     }
  367.     if (column < 0 || column > 200)
  368.     column = 0;
  369.     if (srow >= ep->Lines) {
  370.     srow = ep->Lines - 1;
  371.     goto ra;
  372.     }
  373.     if (dins || srow < ep->Topline || srow >= ep->Topline + Rows) {
  374. ra:
  375.     text_sync();
  376.     --Nsu;
  377.     ep->Line = crow;
  378.     ep->Column = column;
  379.     text_load();
  380.     if (!text_sync())
  381.         text_redisplay();
  382.     } else {
  383.     text_sync();
  384.     --Nsu;
  385.     ep->Line = crow;
  386.     ep->Column = column;
  387.     text_load();
  388.     if (erow != srow) {
  389.         if (!text_sync()) {
  390.         ++erow;
  391.         if (erow - ep->Topline > Rows)
  392.             erow = ep->Topline + Rows;
  393.         SetAPen(rp, ep->BGPen);
  394.         RectFill(rp, COL(0), ROW(srow - ep->Topline), Xbase+Xpixs, ROW(erow - ep->Topline)-1);
  395.         SetAPen(rp, ep->FGPen);
  396.         text_displayseg(srow - ep->Topline, erow - srow);
  397.         }
  398.     } else {
  399.         text_sync();
  400.         if (moded)
  401.         text_redisplaycurrline();
  402.     }
  403.     }
  404.     if (column > Clen) {
  405.     setmem(Current+Clen, column - Clen, ' ');
  406.     Current[column] = 0;
  407.     }
  408.     ep->Column = column;
  409. }
  410.  
  411. void
  412. do_tabstop()
  413. {
  414.     Ep->Tabstop = atoi(av[1]);
  415. }
  416.  
  417. void
  418. do_insertmode()
  419. {
  420.     ED *ep = Ep;
  421.  
  422.     if (av[1][0]) {
  423.     switch(av[1][1] & 0x1F) {
  424.     case 'n'&0x1F:
  425.         ep->Insertmode = 1;
  426.         break;
  427.     case 'f'&0x1F:
  428.         ep->Insertmode = 0;
  429.         break;
  430.     case 'o'&0x1F:
  431.         ep->Insertmode = 1 - ep->Insertmode;
  432.         break;
  433.     }
  434.     if (ep->Insertmode)
  435.         title("Insert mode on");
  436.     else
  437.         title("Insert mode off");
  438.     }
  439. }
  440.  
  441. void
  442. do_insline()
  443. {
  444.     ubyte *ptr;
  445.     ED *ep = Ep;
  446.     RP *rp = ep->Win->RPort;
  447.  
  448.     ep->Modified = 1;
  449.     text_sync();
  450.     if (makeroom(32) && (ptr = allocb(1))) {
  451.     bmovl(ep->List+ep->Line, ep->List+ep->Line+1,ep->Lines-ep->Line);
  452.     ep->List[ep->Line] = ptr;
  453.     *ptr = 0;
  454.     ++ep->Lines;
  455.     if (BEp == ep) {
  456.         if (ep->Line < BSline)
  457.         ++BSline;
  458.         if (ep->Line <= BEline)
  459.         ++BEline;
  460.     }
  461.     } else {
  462.     nomemory();
  463.     }
  464.     text_load();
  465.     if (Nsu == 0)
  466.     ScrollRaster(rp,0,-Ysize, COL(0), ROW(ep->Line-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  467.     text_displayseg(ep->Line - ep->Topline, 1);
  468. }
  469.  
  470. void
  471. do_deline()
  472. {
  473.     int delline;
  474.     ED *ep = Ep;
  475.     RP *rp = ep->Win->RPort;
  476.  
  477.     strcpy(Deline, Current);
  478.     if (ep->Lines > 1) {
  479.     ep->Modified = 1;
  480.     text_sync();
  481.  
  482.     FreeMem(ep->List[ep->Line], strlen(ep->List[ep->Line])+1);
  483.     bmovl(ep->List+ep->Line+1, ep->List+ep->Line,ep->Lines-ep->Line-1);
  484.     if (BEp == ep) {
  485.         if (ep->Line < BSline)
  486.         --BSline;
  487.         if (ep->Line <= BEline)
  488.         --BEline;
  489.     }
  490.     delline = ep->Line;
  491.     if (ep->Line >= --ep->Lines) {
  492.         --ep->Line;
  493.         text_load();
  494.         if (ep->Line < ep->Topline) {
  495.         if (Nsu == 0) {
  496.             ep->Topline = ep->Line - (Rows>>1);
  497.             if (ep->Topline < 0)
  498.             ep->Topline = 0;
  499.             text_redisplay();
  500.         }
  501.         return;
  502.         }
  503.     }
  504.     text_load();
  505.     if (Nsu == 0)
  506.         ScrollRaster(rp,0,Ysize, COL(0), ROW(delline-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  507.     text_displayseg(Rows-1, 1);
  508.     } else {
  509.     do_firstcolumn();
  510.     do_remeol();
  511.     ep->Modified = 0;
  512.     }
  513. }
  514.  
  515. void
  516. do_chfilename()
  517. {
  518.     text_sync();
  519.     strncpy(Ep->Name, av[1], 63);
  520.     MForceTitle = 1;
  521. }
  522.  
  523. void
  524. do_edit()
  525. {
  526.     FILE *fi;
  527.     BPTR oldlock;
  528.     long lines;
  529.     ubyte buf[256];
  530.     ubyte *ptr;
  531.     char failed = 1;
  532.     ED *ep = Ep;
  533.  
  534.     text_sync();
  535.     if (*av[0] == 'n') {        /* newfile or insfile   */
  536.     if (ep->Modified && getyn("Delete modified Image?") == 0)
  537.         return;
  538.     ep = uninit_init(ep);
  539.     strncpy(ep->Name, av[1], 63);
  540.     } else {
  541.     ep->Modified = 1;
  542.     }
  543.     lines = ep->Lines;
  544.     oldlock = CurrentDir((BPTR)ep->dirlock);
  545.     if (fi = fopen(av[1], "r")) {
  546.     int len;
  547.     char oktitle = 1;
  548.  
  549.     title("Loading...");
  550.     while ((len = xefgets(fi, buf, 255)) >= 0) {
  551.         failed = 0;
  552.         if (makeroom(256) && (ptr = allocb(len+1))) {
  553.         ep->List[ep->Lines++] = ptr;
  554.         movmem(buf, ptr, len+1);
  555.         } else {
  556.         set_window_params();
  557.         nomemory();
  558.         oktitle = 0;
  559.         break;
  560.         }
  561.     }
  562.     set_window_params();
  563.     if (oktitle)
  564.         title("OK");
  565.     } else {
  566.     title("File Not Found");
  567. #if AREXX
  568.     cmderr = CMD_FAILED;
  569. #endif
  570.     }
  571.     fclose(fi);
  572.     CurrentDir(oldlock);
  573.     if (ep->Lines != 1 && lines == 1 && ep->List[0][0] == 0) {
  574.     ep->Modified = 0;
  575.     ep->Line = 0;
  576.     FreeMem(ep->List[0], strlen(ep->List[0])+1);
  577.     bmovl(ep->List+1, ep->List,--ep->Lines);
  578.     } else {
  579.     if (!failed && lines <= ep->Lines - 1) {
  580.         BEp = ep;
  581.         BSline = lines;
  582.         BEline = ep->Lines - 1;
  583.         do_bmove();
  584.     }
  585.     }
  586.     set_window_params();
  587.     text_load();
  588.     text_redisplay();
  589. }
  590.  
  591.  
  592. static char blockmode;
  593.  
  594. void
  595. do_bsave()
  596. {
  597.     blockmode = 1;
  598.     do_saveas();
  599. }
  600.  
  601. void
  602. do_save()
  603. {
  604.     av[1] = Ep->Name;
  605.     do_saveas();
  606. }
  607.  
  608. void
  609. do_savetabs()
  610. {
  611.     Savetabs = (av[1][0] && av[1][1] == 'n') ? 1 : 0;
  612. }
  613.  
  614. void
  615. do_saveas()
  616. {
  617.     BPTR oldlock;
  618.     FILE *fi;
  619.     long i;
  620.     short j, k;
  621.     ubyte *ptr, *bp;
  622.     long xs, xe;
  623.     ubyte buf[256];
  624.     char bm;
  625.     ED *ep;
  626.  
  627.     bm = blockmode;
  628.     if (blockmode && blockok()) {
  629.     xs = BSline;
  630.     xe = BEline + 1;
  631.     ep = BEp;
  632.     } else {
  633.     xs = 0;
  634.     xe = Ep->Lines;
  635.     ep = Ep;
  636.     }
  637.     blockmode = 0;
  638.     text_sync();
  639.     oldlock = CurrentDir((BPTR)Ep->dirlock);
  640.     if (Wbs && Wdisable == 0) {     /* Write out .info file */
  641.     DISKOBJ sdo, *d;
  642.     clrmem(&sdo, sizeof(sdo));
  643.     if ((d = GetDiskObject(av[1])) == NULL) {
  644.         if (getpathto(Wbs->sm_ArgList[0].wa_Name, buf)) {
  645.         sdo.do_Magic = WB_DISKMAGIC;
  646.         sdo.do_Version = WB_DISKVERSION;
  647.         makemygadget(&sdo.do_Gadget);
  648.         sdo.do_Type = WBPROJECT;
  649.         sdo.do_DefaultTool = (char *)buf;
  650.         sdo.do_ToolTypes = NULL;
  651.         sdo.do_CurrentX = NO_ICON_POSITION;
  652.         sdo.do_CurrentY = NO_ICON_POSITION;
  653.         sdo.do_DrawerData = NULL;
  654.         sdo.do_ToolWindow = NULL;
  655.         sdo.do_StackSize = 8192;
  656.         PutDiskObject(av[1], &sdo);
  657.         }
  658.     } else {
  659.         FreeDiskObject(d);
  660.     }
  661.     }
  662.     if (fi = fopen(av[1], "w")) {
  663.     title("Saving...");
  664.     for (i = xs; i < xe; ++i) {
  665.         ptr = ep->List[i];
  666.         if (Savetabs) {
  667.         for (bp = buf, j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
  668.             *bp = *ptr;
  669.             if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
  670.             k = j;
  671.             while (k-- >= 0 && *bp == ' ')
  672.                 --bp;
  673.             *++bp = 9;
  674.             } else {
  675.             if (*bp < 32 || *bp == '\"' || *bp == '\'' || *bp == '\`' || *bp == '(')
  676.                 break;
  677.             }
  678.         }
  679.         strcpy(bp, ptr);
  680.         ptr = buf;
  681.         }
  682.         fputs(ptr, fi);
  683.         fputc('\n', fi);
  684.     }
  685.     if (fclose(fi)) {
  686. err:        Abortcommand = 1;
  687.         title("WRITE FAILED!");
  688.     } else {
  689.         ep->Modified &= bm;
  690.         title("OK");
  691.     }
  692.     } else {
  693.     title("Unable to open write file");
  694.     Abortcommand = 1;
  695.     }
  696.     CurrentDir(oldlock);
  697. }
  698.  
  699. void
  700. do_block()          /* block, unblock   */
  701. {
  702.     text_sync();
  703.  
  704.     switch(av[0][0]) {
  705.     case 'b':
  706.     if (BSline < 0) {
  707. bstart:
  708.         BEp = Ep;
  709.         BSline = Ep->Line;
  710.         title("Block Begin");
  711.     } else {
  712.         if (BEline > -1) {
  713.         title("Block Already Marked");
  714.         break;
  715.         }
  716.         if (BEp != Ep)
  717.         goto bstart;
  718.         title("Block End");
  719.         BEline = Ep->Line;
  720.         if (BSline > BEline) {
  721.         BEline = BSline;
  722.         BSline = Ep->Line;
  723.         }
  724.         text_redrawblock(1);
  725.     }
  726.     break;
  727.     case 'u':
  728.     text_redrawblock(0);
  729.     title ("Block Unmarked");
  730.     break;
  731.     }
  732. }
  733.  
  734.  
  735. blockok()
  736. {
  737.     if (BEp && BSline >= 0 && BSline <= BEline && BEline < BEp->Lines)
  738.     return(1);
  739.     BEp = NULL;
  740.     BSline = BEline = -1;
  741.     title("Block Not Specified");
  742.     return(0);
  743. }
  744.  
  745. void
  746. do_bdelete()
  747. {
  748.     long n;
  749.     ED *bep = BEp;
  750.     WIN *savewin = Ep->Win;
  751.  
  752.     if (blockok()) {
  753.     text_switch(bep->Win);
  754.     n = BEline - BSline + 1;
  755.     if (bep->Line >= BSline && bep->Line <= BEline)
  756.         bep->Line = BSline;
  757.     if (bep->Line > BEline)
  758.         bep->Line -= n;
  759.     freelist(bep->List + BSline, BEline - BSline + 1);
  760.     bmovl(bep->List+BEline+1,bep->List+BSline,(bep->Lines-BEline-1));
  761.     bep->Lines -= n;
  762.     bep->Modified = 1;
  763.     if (bep->Line >= bep->Lines)
  764.         bep->Line = bep->Lines - 1;
  765.     if (bep->Line < 0)
  766.         bep->Line = 0;
  767.     if (bep->Lines == 0) {
  768.         ++bep->Lines;
  769.         bep->List[0] = allocb(1);
  770.         bep->List[0][0] = 0;
  771.     }
  772.     text_load();
  773.     BEp = NULL;
  774.     BSline = BEline = -1;
  775.     if (!text_sync())
  776.         text_redisplay();
  777.     text_switch(savewin);
  778.     }
  779. }
  780.  
  781. void
  782. do_bcopy()
  783. {
  784.     ubyte **list;
  785.     long lines, i;
  786.     ED *ep = Ep;
  787.  
  788.     text_sync();
  789.     if (!blockok())
  790.     return;
  791.     if (ep == BEp && ep->Line > BSline && ep->Line <= BEline) {
  792.     title("Cannot Move into self");
  793.     return;
  794.     }
  795.     lines = BEline - BSline + 1;
  796.     if (extend(ep, lines)) {
  797.     if (list = (ubyte **)allocl(lines)) {
  798.         bmovl(BEp->List+BSline,list,lines);
  799.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  800.         for (i = 0; i < lines; ++i) {
  801.         ubyte *str = allocb(strlen(list[i])+1);
  802.         if (!str) {
  803.             nomemory();
  804.             FreeMem(list, lines * sizeof(char *));
  805.             freelist(ep->List + Ep->Line, i);
  806.             bmovl(ep->List+ep->Line+lines, ep->List+ep->Line, ep->Lines-ep->Line);
  807.             return;
  808.         }
  809.         strcpy(str, list[i]);
  810.         ep->List[ep->Line+i] = str;
  811.         }
  812.         FreeMem(list, lines * sizeof(char *));
  813.     }
  814.     }
  815.     if (ep == BEp && ep->Line <= BSline) {
  816.     BSline += lines;
  817.     BEline += lines;
  818.     }
  819.     ep->Modified = 1;
  820.     ep->Lines += lines;
  821.     text_load();
  822.     if (!text_sync())
  823.     text_redisplay();
  824. }
  825.  
  826.  
  827. void
  828. do_bmove()
  829. {
  830.     long lines;
  831.     ubyte **list;
  832.     ED *ep = Ep;
  833.  
  834.     text_sync();
  835.     if (!blockok())
  836.     return;
  837.     if (BEp == ep && ep->Line >= BSline && ep->Line <= BEline) {
  838.     title("Cannot Move into self");
  839.     return;
  840.     }
  841.     lines = BEline - BSline + 1;
  842.     if (!(list = (ubyte **)allocl(lines))) {
  843.     nomemory();
  844.     return;
  845.     }
  846.     BEp->Modified = ep->Modified = 1;
  847.     bmovl(BEp->List + BSline, list, lines);
  848.     if (ep == BEp) {
  849.     if (ep->Line > BSline) {
  850.         bmovl(ep->List+BEline+1, ep->List+BSline, ep->Line-BEline-1);
  851.         bmovl(list, ep->List + ep->Line - lines, lines);
  852.     } else {
  853.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, BSline-ep->Line);
  854.         bmovl(list, ep->List + ep->Line, lines);
  855.     }
  856.     } else {
  857.     WIN *savewin = ep->Win;
  858.     if (extend(ep, lines)) {
  859.         bmovl(BEp->List+BEline+1, BEp->List+BSline, BEp->Lines-BEline-1);
  860.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  861.         bmovl(list, ep->List+ep->Line, lines);
  862.         ep->Lines += lines;
  863.         BEp->Lines -= lines;
  864.         if (BEp->Line >= BSline && BEp->Line <= BEline)
  865.         BEp->Line = BSline - 1;
  866.         if (BEp->Line > BEline)
  867.         BEp->Line -= lines;
  868.         if (BEp->Line < 0)
  869.         BEp->Line = 0;
  870.         BSline = BEline = -1;
  871.         if (BEp->Lines == 0) {
  872.         ubyte *ptr = allocb(1);
  873.         BEp->List[0] = ptr;
  874.         *ptr = 0;
  875.         ++BEp->Lines;
  876.         }
  877.         text_load();
  878.         text_switch(BEp->Win);
  879.         BEp = NULL;
  880.         ep = Ep;
  881.         if (!ep->iconmode) {
  882.         if (!text_sync())
  883.             text_redisplay();
  884.         }
  885.         text_switch(savewin);
  886.         ep = Ep;
  887.     }
  888.     }
  889.     BSline = BEline = -1;
  890.     BEp = NULL;
  891.     FreeMem(list, lines * sizeof(char *));
  892.     ep->Modified = 1;
  893.     text_load();
  894.     if (!text_sync())
  895.     text_redisplay();
  896. }
  897.  
  898.  
  899. /*
  900.  * IF condition trueaction, IFELSE condition trueaction falseaction
  901.  *
  902.  *  condition:    !condition NOT the specified condition.
  903.  *        #       toggle number is SET
  904.  *        top       top of file (on first line)
  905.  *        bot       end of file (on last line)
  906.  *        left       start of line (leftmost column)
  907.  *        right       end of line (nothing but spaces under and to the right)
  908.  *        modified   text has been modified
  909.  *        insert       currently in insert mode
  910.  *        y[<=>]#    cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  911.  *        x[<=>]#    cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  912.  *                <> means 'not equal'
  913.  *
  914.  *        cl       char under cursor is lower case
  915.  *        cu       char under cursor is upper case
  916.  *        ca       char under cursor is alpha
  917.  *        cn       char under cursor is numeric
  918.  *        cb       char within selected block
  919.  *        c[<=>]#    char under cursor is (combo of <,>,and =) #
  920.  */
  921.  
  922. void
  923. do_if()
  924. {
  925.     char haselse = (av[0][2] == 'e');
  926.     char iswhile = (av[0][0] == 'w');
  927.     char istrue, notop = 0;
  928.     char c, cx, cc;
  929.     ubyte *buf1, *buf2;
  930.     ubyte *ptr;
  931.     ED *ep = Ep;
  932.     int i, cxn, cn;
  933.  
  934.     buf1 = (ubyte *)malloc(256);
  935.     buf2 = (ubyte *)malloc(256);
  936.     if (buf1 == NULL || buf2 == NULL) {
  937.     if (buf1) free(buf1);
  938.     if (buf2) free(buf2);
  939.     title("No Memory!");
  940.     return;
  941.     }
  942.     breakreset();
  943.     ptr = av[1];
  944.     if (*ptr == '!') {
  945.     notop = 1;
  946.     ++ptr;
  947.     }
  948.     c = ptr[0];
  949.     cn= atoi(ptr);
  950.     cx= ptr[1];
  951.     cxn=atoi(ptr+1);
  952.     strcpy(buf1, av[2]);
  953.  
  954. loop:
  955.     istrue = 0;
  956.     i = 0;
  957.     switch(c) {
  958.     case 'x':
  959.     i = ep->Column + 1;
  960.     case 'y':
  961.     if (!i)
  962.         i = ep->Line + 1;
  963. conditional:
  964.     {
  965.         int j, n;
  966.         char any = 0;
  967.  
  968.         for (j = 1; ptr[j] && (ptr[j]<'0'||ptr[j]>'9'); ++j);
  969.         n = atoi(ptr+j);
  970.         for (j = 1; ptr[j]; ++j) {
  971.         switch(ptr[j]) {
  972.         case '<':
  973.             any = 1;
  974.             if (i < n)
  975.             istrue = 1;
  976.             break;
  977.         case '=':
  978.             any = 1;
  979.             if (i == n)
  980.             istrue = 1;
  981.             break;
  982.         case '>':
  983.             any = 1;
  984.             if (i > n)
  985.             istrue = 1;
  986.             break;
  987.         }
  988.         }
  989.         if (!any && i == n)  /* default is equivalence   */
  990.         istrue = 1;
  991.     }
  992.     break;
  993.     case 't':
  994.     istrue = ep->Line == 0;
  995.     break;
  996.     case 'b':
  997.     istrue = ep->Line == ep->Lines-1;
  998.     break;
  999.     case 'l':
  1000.     istrue = ep->Column == 0;
  1001.     break;
  1002.     case 'r':
  1003.     istrue = ep->Column == Clen;
  1004.     break;
  1005.     case 'm':
  1006.     text_sync();
  1007.     istrue = ep->Modified != 0;
  1008.     break;
  1009.     case 'e':
  1010.     istrue = Comlinemode != 0;
  1011.     break;
  1012.     case 'i':
  1013.     istrue = ep->Insertmode != 0;
  1014.     break;
  1015.     case 'c':
  1016.     cc = Current[ep->Column];
  1017.     switch(cx) {
  1018.     case 'b':
  1019.         istrue = BEp == ep && ep->Line >= BSline && ep->Line <= BEline;
  1020.         break;
  1021.     case 'l':
  1022.         istrue = cc >= 'a' && cc <= 'z';
  1023.         break;
  1024.     case 'u':
  1025.         istrue = cc >= 'A' && cc <= 'Z';
  1026.         break;
  1027.     case 'a':
  1028.         istrue = (cc>='a'&&cc<='z')||(cc>='A'&&cc<='Z')||(cc>='0'&&cc<='9');
  1029.         break;
  1030.     case 'n':
  1031.         istrue = (cc >= '0' && cc <= '9');
  1032.         break;
  1033.     default:        /* c[<=>]#  */
  1034.         i = Current[ep->Column];
  1035.         goto conditional;
  1036.         break;
  1037.     }
  1038.     break;
  1039.     default:
  1040.     if (c >= '0' && c <= '9')
  1041.         istrue = do_toggle(cn) != 0;
  1042.     else
  1043.         title("bad conditional");
  1044.     break;
  1045.     }
  1046.     istrue ^= notop;
  1047.     if (istrue) {
  1048.     strcpy(buf2, buf1);     /* could be executed multiple times */
  1049.     if (do_command(buf2) == 0)
  1050.         goto done;
  1051.     if (iswhile) {
  1052.         if (breakcheck())
  1053.         Abortcommand = 1;
  1054.         else
  1055.         goto loop;
  1056.     }
  1057.     } else {
  1058.     if (haselse) {          /* only executed once */
  1059.         strcpy(buf2, av[3]);
  1060.         do_command(buf2);
  1061.     }
  1062.     }
  1063. done:
  1064.     free(buf1);
  1065.     free(buf2);
  1066. }
  1067.  
  1068.  
  1069. /*
  1070.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  1071.  */
  1072.  
  1073. do_toggle(n)
  1074. {
  1075.     static char tg[MAXTOGGLE];
  1076.     int i;
  1077.  
  1078.     if (n >= 0) {
  1079.     if (n >= MAXTOGGLE)
  1080.         return(0);
  1081.     return((int)tg[n]);
  1082.     }
  1083.     i = atoi(av[1]);
  1084.     if (i >= 0 && i < MAXTOGGLE) {
  1085.     switch(av[0][0]) {
  1086.     case 't':
  1087.         tg[i] = !tg[i];
  1088.         break;
  1089.     case 's':
  1090.         tg[i] = 1;
  1091.         break;
  1092.     case 'r':
  1093.         tg[i] = 0;
  1094.         break;
  1095.     }
  1096.     }
  1097. }
  1098.  
  1099.  
  1100. void
  1101. do_tlate()
  1102. {
  1103.     ubyte *ptr = av[1];
  1104.     ED *ep = Ep;
  1105.     char c = Current[ep->Column];
  1106.  
  1107.     if (c == 0)
  1108.     c = ' ';
  1109.     if (ptr[0] == '+')
  1110.     c += atoi(ptr+1);
  1111.     else
  1112.     if (ptr[0] == '-')
  1113.     c -= atoi(ptr+1);
  1114.     else
  1115.     c = atoi(ptr);
  1116.     if (c) {
  1117.     if (Current[ep->Column] == 0) {
  1118.         Clen = ep->Column + 1;
  1119.         Current[Clen] = 0;
  1120.     }
  1121.     Current[ep->Column] = c;
  1122.     if (Nsu == 0) {
  1123.         movetocursor();
  1124.         setpen(ep->Line);
  1125.         Text(ep->Win->RPort, Current+ep->Column, 1);
  1126.     }
  1127.     }
  1128. }
  1129.  
  1130. /*
  1131.  *  BSOURCE
  1132.  *
  1133.  *  note that since the start and end lines are loaded immediately and the
  1134.  *  block unblock'd before execution starts, you can theoretically have
  1135.  *  another BSOURCE as part of this BSOURCE (but be carefull!).
  1136.  */
  1137.  
  1138. void
  1139. do_bsource()
  1140. {
  1141.     ubyte buf[256];
  1142.     int i, sl, se;
  1143.  
  1144.     if (blockok()) {
  1145.     sl = BSline;
  1146.     se = BEline + 1;
  1147.     for (i = sl; BEp && i < se && i < BEp->Lines; ++i) {
  1148.         text_sync();        /* make sure we are using latest text */
  1149.         strcpy(buf, BEp->List[i]);
  1150.         if (do_command(buf) == 0)
  1151.         break;
  1152.     }
  1153.     text_redrawblock(0);
  1154.     }
  1155. }
  1156.  
  1157. /*
  1158.  *  SCANF controlstring
  1159.  *
  1160.  *  The C scanf routine.  Only one variable, a string, is allowed in the
  1161.  *  control string.
  1162.  */
  1163.  
  1164. void
  1165. do_scanf()
  1166. {
  1167.     char buf[256];
  1168.  
  1169.     buf[0] = 0;
  1170.     sscanf(Current+Ep->Column,av[1],buf,buf,buf,buf,buf,buf,buf);
  1171.     if (String)
  1172.     free(String);
  1173.     String = (char *)malloc(strlen(buf)+1);
  1174.     strcpy(String,buf);
  1175.     title(String);
  1176. }
  1177.  
  1178. void
  1179. movetocursor()
  1180. {
  1181.     ED *ep = Ep;
  1182.     Move(ep->Win->RPort, XTbase+(ep->Column-ep->Topcolumn)*Xsize, YTbase+(ep->Line-ep->Topline)*Ysize);
  1183. }
  1184.  
  1185. extend(ep, lines)
  1186. ED *ep;
  1187. {
  1188.     long extra = ep->Maxlines - ep->Lines;
  1189.     ubyte **list;
  1190.  
  1191.     if (lines > extra) {
  1192.     lines += ep->Lines;
  1193.     if (list = (ubyte **)allocl(lines)) {
  1194.         bmovl(ep->List, list, ep->Lines);
  1195.         FreeMem(ep->List, sizeof(char *) * ep->Maxlines);
  1196.         ep->Maxlines = lines;
  1197.         ep->List = list;
  1198.         return(1);
  1199.     }
  1200.     nomemory();
  1201.     return(0);
  1202.     }
  1203.     return(1);
  1204. }
  1205.  
  1206. makeroom(n)
  1207. {
  1208.     ED *ep = Ep;
  1209.     if (ep->Lines >= ep->Maxlines)
  1210.     return(extend(ep, n));
  1211.     return(1);
  1212. }
  1213.  
  1214. void
  1215. freelist(list, n)
  1216. char **list;
  1217. {
  1218.     while (n) {
  1219.     FreeMem(list[0], strlen(list[0])+1);
  1220.     ++list;
  1221.     --n;
  1222.     }
  1223. }
  1224.  
  1225.